/**
 * 
 */
package org.rollinitiative.d20.entity;

import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.xmlbeans.XmlException;
import org.exist.xmldb.XQueryService;
import org.rollinitiative.d20.persist.PersistenceBridge;
import org.rollinitiative.d20.schema.character.CharacterType;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;

/**
 * This class bridges the domains of data content and data persistence for Character related
 * content.
 * 
 * @author bebopjmm
 * 
 */
public class CharacterBridge extends PersistenceBridge
{
    final static Log LOG_ = LogFactory.getLog(CharacterBridge.class);

    Collection characterCollection_;

    public CharacterBridge(XMLConfiguration config)
    {
        super(config);
        LOG_.info("Assigned config. Root element name = " + config.getRootElementName());
    }


    /**
     * This method loads the collection where campaign is directly off the root collection of the
     * repository, and characterCollection is directly off the campaign.
     * 
     * @param campaign
     * @param characterCollection
     */
    public void loadCollection(String campaign, String characterCollection)
    {
        try {
            connect(campaign);
            characterCollection_ = retrieveCollection(characterCollection);
            xqueryService = (XQueryService) characterCollection_
                    .getService("XQueryService", "1.0");
        } catch (XMLDBException ex) {
            LOG_.error("Failed to load the characre collection collection: " + characterCollection);
        }
    }


    /**
     * This method returns the D20 CharacterType information for the character identified by
     * characterID. Currently the name attribute is used as the characterID.
     * 
     * @param characterID Identification attribute of the character being retrieved
     * @return CharacterType for the character identified by characterID, null if not found.
     */
    public CharacterType getCharacter(String characterID)
    {
        String indexQuery = config.getString("characterBridge.queries.characterByID");
        indexQuery = indexQuery.replace("#ID#", characterID);

        LOG_.debug("Parameterized Query: " + indexQuery);
        ResourceSet results = query(indexQuery);

        try {
            CharacterType character = CharacterType.Factory.parse(results.getResource(0)
                    .getContent().toString(), xmlOptions);
            return character;
        } catch (XmlException xmlEx) {
            LOG_.error("Failure marshalling into xmlbean", xmlEx);
            return null;
        } catch (XMLDBException xmldbEx) {
            LOG_.error("Failure processing ResourceSet", xmldbEx);
            return null;
        }
    }


    /**
     * This method returns an array of D20 Characters that are members of the named group.
     * 
     * @param groupName Name of group to query membership
     * @return array of D20 characters in named group, empty array if group not found or empty
     */
    public CharacterType[] getGroup(String groupName)
    {
        String indexQuery = config.getString("characterBridge.queries.group");
        indexQuery = indexQuery.replace("#NAME#", groupName);

        LOG_.debug("Parameterized Query: " + indexQuery);
        ResourceSet results = query(indexQuery);
        CharacterType[] group = null;
        if (results == null) {
            LOG_.warn("Returning EMPTY array due to NULL ResultSet for query on groupName: "
                    + groupName);
            return new CharacterType[0];
        }

        try {
            group = new CharacterType[(int) results.getSize()];
            for (int i = 0; i < group.length; i++) {
                group[i] = CharacterType.Factory.parse(results.getResource(i).getContent()
                        .toString(), xmlOptions);
            }

        } catch (XmlException xmlEx) {
            LOG_.error("Failure marshalling into xmlbean", xmlEx);
            return new CharacterType[0];
        } catch (XMLDBException xmldbEx) {
            LOG_.error("Failure processing ResourceSet", xmldbEx);
            return new CharacterType[0];
        }
        return group;
    }

}
